home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / std / c++ / 1167 < prev    next >
Encoding:
Internet Message Format  |  1996-08-06  |  3.8 KB

  1. From: Nico Josuttis <nico@bredex.de>
  2. Message-ID: <199604191427.QAA11829@bredex.bredex.de>
  3. X-Original-Date: Fri, 19 Apr 1996 16:27:09 +0200
  4. Path: in2.uu.net!bounce-back
  5. Date: 19 Apr 96 14:54:19 GMT
  6. Approved: fjh@cs.mu.oz.au
  7. Newsgroups: comp.std.c++
  8. Subject: STL bug with example: remove_if() looses function state
  9. References: <199604110827.KAA02243@bredex.bredex.de>
  10. Reply-To: nico@bredex.de
  11. Organization: Bredex GmbH
  12. Keywords: STL 
  13. Apparently-To: nico@bredex.de
  14. Apparently-To: std-c++@ncar.ucar.edu
  15. X-Auth: PGPMoose V1.1 PGP comp.std.c++
  16.     iQBEAgUBMXepOuEDnX0m9pzZAQHFcgF4gf/i3i0mE5lSWX3B07Dh5RTFCr5nn60h
  17.     6/nUjwzWhh9b7EuHV5PowyIiL5vtVXQ=
  18.     =hP/o
  19.  
  20. Some people asked for an example of my remove_if() problem.
  21. Here is the problem with example.
  22.  
  23. The example uses remove_if() to remove only the first element
  24. with a given value.
  25. A function object (that has no side effects)
  26. is designed to return true only for the first
  27. element having a given value.
  28. But using it as parameter of remove_if(), it is
  29. duplicated and thus does return true twice.
  30. That results in removing not only the first but also the
  31. second element. OOOPS
  32.  
  33. ------------------------- snip -----------
  34. #include <iostream>
  35. #include <list>
  36. #include <algorithm>
  37. using namespace std;
  38.  
  39. class FirstElemWithValue {
  40.   private:
  41.     int  value;
  42.     bool found;
  43.   public:
  44.     FirstElemWithValue (int v) : value(v), found(false) {
  45.     }
  46.     bool operator() (int elem) {
  47.     // return true only for the first found elem
  48.         if (!found && elem == value) {
  49.             found = true;
  50.             return true;
  51.         }
  52.         return false;
  53.     }
  54. };
  55.  
  56. int main ()
  57. {
  58.     list<int> m;
  59.  
  60.     m.push_back (1);
  61.     m.push_back (2);
  62.     m.push_back (4);
  63.     m.push_back (3);
  64.     m.push_back (5);
  65.     m.push_back (6);
  66.     m.push_back (2);
  67.     m.push_back (0);
  68.     m.push_back (2);
  69.  
  70.     copy (m.begin(), m.end(), ostream_iterator<int>(cout," "));
  71.     cout << endl;
  72.  
  73.     /* remove first element with value 2
  74.      */
  75.     list<int>::iterator pos;
  76.     pos = remove_if (m.begin(), m.end(),
  77.              FirstElemWithValue(2));
  78.     m.erase (pos, m.end());
  79.  
  80.     copy (m.begin(), m.end(), ostream_iterator<int>(cout," "));
  81.     cout << endl;
  82. }
  83. ------------------- snip --------------------------
  84.  
  85. The output is:
  86.  1 2 4 3 5 6 2 0 2
  87.  1 4 3 5 6 0 2
  88. but should be:
  89.  1 2 4 3 5 6 2 0 2
  90.  1 4 3 5 6 2 0 2
  91.  
  92. This happens due to the current implementation of
  93. remove_if() which calls find_if() and remove_copy_if():
  94.  
  95.  > template <class ForwardIterator, class Predicate>
  96.  > ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,
  97.  >                           Predicate pred) {
  98.  >   first = find_if(first, last, pred);
  99.  >   ForwardIterator next = first;
  100.  >   return first == last ? first : remove_copy_if(++next, last, first, pred);
  101.  > }
  102.  
  103. So pred() is called with two different copies of
  104. FirstElemWithValue.
  105.  
  106. I think it would be better/necessary to disallow such implementations,
  107. what means to disallow that a function object gets copied before
  108. calling operator().  At least it should not be allowed that operator()
  109. is called by different copies of the function object.  Otherwise we
  110. would lose the advantage of function objects in a significant matter.
  111.  
  112. Am I missing something ?
  113.  
  114. -- 
  115. Nico                             address: BREDEX GmbH, Nicolai Josuttis
  116. email:   nico@bredex.de                   Fallersleber-Tor-Wall 23
  117. phone:   +49 531 24330-0                  D-38100 Braunschweig
  118. fax:     +49 531 24330-99                 Germany
  119. ---
  120. [ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
  121. [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
  122. [ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
  123. [ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
  124. [ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]
  125.